/**
 ******************************************************************************
 * @file           : bsp_adc.c
 * @brief          : ADC Driver Implementation (STM32F4xx)
 ******************************************************************************
 * @attention
 *
 * ADC驱动实现文件
 * 使用DMA Stream进行多通道连续采集
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/ADC/bsp_adc.h"
#include "./BSP/ADC/bsp_adc_config.h"

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static ADC_HandleTypeDef sg_adc_handle;
static volatile ADC_State_e sg_adc_state = ADC_STATE_IDLE;  /*!< ADC当前状态 */

#if (ADC_USE_DMA == 1)
static DMA_HandleTypeDef sg_dma_handle;
static uint16_t sg_adc_values[ADC_CHANNEL_NUM];  /* DMA缓冲区 */
#endif

#if (ADC_FILTER_ENABLE == 1)
static uint16_t sg_filter_last_values[ADC_CHANNEL_NUM] = {0};  /* 滤波上一次值 */
static uint8_t sg_filter_initialized[ADC_CHANNEL_NUM] = {0};   /* 滤波初始化标志 */
#endif

/* Private function prototypes -----------------------------------------------*/
static void adc_gpio_init(uint32_t channel);
static uint32_t adc_get_hal_channel(uint32_t channel);
#if (ADC_FILTER_ENABLE == 1)
static uint16_t adc_filter(uint16_t new_value, uint8_t channel);
#endif

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       ADC GPIO初始化
 *
 * @param[in]   channel ADC通道号（0~15）
 *
 * @retval      无
 *
 * @note        配置对应GPIO为模拟输入模式
 */
static void adc_gpio_init(uint32_t channel)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    GPIO_TypeDef *gpio_port = NULL;
    uint16_t gpio_pin = 0;

    /* 根据通道号确定GPIO引脚 */
    switch (channel)
    {
        /* ADC123通道0~3：PA0~PA3 */
        case 0: gpio_port = GPIOA; gpio_pin = GPIO_PIN_0; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 1: gpio_port = GPIOA; gpio_pin = GPIO_PIN_1; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 2: gpio_port = GPIOA; gpio_pin = GPIO_PIN_2; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 3: gpio_port = GPIOA; gpio_pin = GPIO_PIN_3; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        
        /* ADC12通道4~7：PA4~PA7 */
        case 4: gpio_port = GPIOA; gpio_pin = GPIO_PIN_4; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 5: gpio_port = GPIOA; gpio_pin = GPIO_PIN_5; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 6: gpio_port = GPIOA; gpio_pin = GPIO_PIN_6; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case 7: gpio_port = GPIOA; gpio_pin = GPIO_PIN_7; __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        
        /* ADC12通道8~9：PB0~PB1 */
        case 8: gpio_port = GPIOB; gpio_pin = GPIO_PIN_0; __HAL_RCC_GPIOB_CLK_ENABLE(); break;
        case 9: gpio_port = GPIOB; gpio_pin = GPIO_PIN_1; __HAL_RCC_GPIOB_CLK_ENABLE(); break;
        
        /* ADC123通道10~13：PC0~PC3 */
        case 10: gpio_port = GPIOC; gpio_pin = GPIO_PIN_0; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        case 11: gpio_port = GPIOC; gpio_pin = GPIO_PIN_1; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        case 12: gpio_port = GPIOC; gpio_pin = GPIO_PIN_2; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        case 13: gpio_port = GPIOC; gpio_pin = GPIO_PIN_3; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        
        /* ADC12通道14~15：PC4~PC5 */
        case 14: gpio_port = GPIOC; gpio_pin = GPIO_PIN_4; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        case 15: gpio_port = GPIOC; gpio_pin = GPIO_PIN_5; __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        
        default: return;
    }

    /* 配置GPIO为模拟输入模式 */
    gpio_init_struct.Pin = gpio_pin;
    gpio_init_struct.Mode = GPIO_MODE_ANALOG;
    gpio_init_struct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(gpio_port, &gpio_init_struct);
}

/**
 * @brief       获取HAL库通道定义
 *
 * @param[in]   channel 通道号（0~15）
 *
 * @retval      HAL库通道定义
 */
static uint32_t adc_get_hal_channel(uint32_t channel)
{
    const uint32_t channel_map[] = {
        ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_3,
        ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6, ADC_CHANNEL_7,
        ADC_CHANNEL_8, ADC_CHANNEL_9, ADC_CHANNEL_10, ADC_CHANNEL_11,
        ADC_CHANNEL_12, ADC_CHANNEL_13, ADC_CHANNEL_14, ADC_CHANNEL_15
    };

    if (channel < 16)
    {
        return channel_map[channel];
    }

    return ADC_CHANNEL_0;
}

#if (ADC_FILTER_ENABLE == 1)
/**
 * @brief       ADC数据一阶低通滤波
 *
 * @param[in]   new_value 新的ADC采样值
 * @param[in]   channel 通道索引(0 ~ ADC_CHANNEL_NUM-1)
 *
 * @retval      滤波后ADC值
 *
 * @note        滤波公式: y(n) = α·x(n) + (1-α)·y(n-1)
 * @note        每个通道第一次调用时直接使用真实值初始化
 */
static uint16_t adc_filter(uint16_t new_value, uint8_t channel)
{
    if (channel >= ADC_CHANNEL_NUM)
    {
        log_w("Filter channel invalid: %d", channel);
        return new_value;
    }

    if (!sg_filter_initialized[channel])
    {
        sg_filter_last_values[channel] = new_value;
        sg_filter_initialized[channel] = 1;
        return new_value;
    }

    float filtered = ADC_FILTER_ALPHA * (float)new_value + 
                    (1.0f - ADC_FILTER_ALPHA) * (float)sg_filter_last_values[channel];
    sg_filter_last_values[channel] = (uint16_t)filtered;

    return (uint16_t)filtered;
}
#endif

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       ADC初始化
 *
 * @param[in]   channels 通道数组（例如：{0, 1}表示通道0和通道1）
 * @param[in]   num 通道数量
 *
 * @retval      无
 *
 * @note        初始化ADC和DMA
 */
void adc_init(const uint32_t *channels, uint8_t num)
{
    ADC_ChannelConfTypeDef adc_channel_config = {0};
    uint8_t i;

    if (channels == NULL || num == 0 || num > ADC_CHANNEL_NUM)
    {
        log_e("Invalid ADC channel parameters");
        return;
    }

    /* 使能ADC时钟 */
    ADC_ADCx_CLK_ENABLE();

    /* 初始化GPIO */
    for (i = 0; i < num; i++)
    {
        adc_gpio_init(channels[i]);
    }

#if (ADC_USE_DMA == 1)
    /* 使能DMA时钟 */
    ADC_DMAx_CLK_ENABLE();

    /* 配置DMA */
    sg_dma_handle.Instance = ADC_DMAx_STREAMx;
    sg_dma_handle.Init.Channel = ADC_DMAx_CHANNELx;
    sg_dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    sg_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;
    sg_dma_handle.Init.MemInc = DMA_MINC_ENABLE;
    sg_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    sg_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    sg_dma_handle.Init.Mode = DMA_CIRCULAR;
    sg_dma_handle.Init.Priority = DMA_PRIORITY_HIGH;
    sg_dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

    if (HAL_DMA_Init(&sg_dma_handle) != HAL_OK)
    {
        log_e("DMA initialization failed");
        return;
    }

    /* 关联DMA和ADC */
    __HAL_LINKDMA(&sg_adc_handle, DMA_Handle, sg_dma_handle);
#endif

    /* 配置ADC */
    sg_adc_handle.Instance = ADC_ADCx;
    sg_adc_handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    sg_adc_handle.Init.Resolution = ADC_RESOLUTION_CONFIG;
    sg_adc_handle.Init.ScanConvMode = (num > 1) ? ENABLE : DISABLE;
    sg_adc_handle.Init.ContinuousConvMode = ENABLE;
    sg_adc_handle.Init.DiscontinuousConvMode = DISABLE;
    sg_adc_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    sg_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    sg_adc_handle.Init.NbrOfConversion = num;
    sg_adc_handle.Init.DMAContinuousRequests = ENABLE;
    sg_adc_handle.Init.EOCSelection = ADC_EOC_SEQ_CONV;

    if (HAL_ADC_Init(&sg_adc_handle) != HAL_OK)
    {
        log_e("ADC initialization failed");
        return;
    }

    /* 配置ADC通道 */
    for (i = 0; i < num; i++)
    {
        adc_channel_config.Channel = adc_get_hal_channel(channels[i]);
        adc_channel_config.Rank = i + 1;
        adc_channel_config.SamplingTime = ADC_SAMPLETIME_CONFIG;

        if (HAL_ADC_ConfigChannel(&sg_adc_handle, &adc_channel_config) != HAL_OK)
        {
            log_e("ADC channel %u configuration failed", channels[i]);
            return;
        }
    }

    log_i("ADC%d initialized: %d channels, %d-bit", ADC_SELECT_NUM, num, ADC_RESOLUTION);
}

/**
 * @brief       ADC去初始化
 *
 * @param       无
 *
 * @retval      无
 */
void adc_deinit(void)
{
#if (ADC_USE_DMA == 1)
    /* 去初始化DMA */
    HAL_DMA_DeInit(&sg_dma_handle);
#endif

    /* 去初始化ADC */
    HAL_ADC_DeInit(&sg_adc_handle);

    log_i("ADC%d deinitialized", ADC_SELECT_NUM);
}

/**
 * @brief       读取单个通道ADC值（单次转换）
 *
 * @param[in]   channel 通道号（0~15）
 *
 * @retval      ADC值（0~ADC_MAX_VALUE）
 */
uint16_t adc_read_channel(uint32_t channel)
{
    ADC_ChannelConfTypeDef adc_channel_config = {0};
    uint16_t value = 0;

    /* 配置通道 */
    adc_channel_config.Channel = adc_get_hal_channel(channel);
    adc_channel_config.Rank = 1;
    adc_channel_config.SamplingTime = ADC_SAMPLETIME_CONFIG;

    if (HAL_ADC_ConfigChannel(&sg_adc_handle, &adc_channel_config) != HAL_OK)
    {
        return 0;
    }

    /* 启动ADC转换 */
    HAL_ADC_Start(&sg_adc_handle);

    /* 等待转换完成 */
    if (HAL_ADC_PollForConversion(&sg_adc_handle, 100) == HAL_OK)
    {
        value = HAL_ADC_GetValue(&sg_adc_handle);
    }

    /* 停止ADC */
    HAL_ADC_Stop(&sg_adc_handle);

    return value;
}

/**
 * @brief       读取单个通道电压值（单次转换）
 *
 * @param[in]   channel 通道号（0~15）
 *
 * @retval      电压值（mV）
 */
uint16_t adc_read_voltage(uint32_t channel)
{
    uint16_t adc_value = adc_read_channel(channel);
    uint32_t voltage = (uint32_t)adc_value * ADC_VREF_MV / ADC_MAX_VALUE;
    
    return (uint16_t)voltage;
}

#if (ADC_USE_DMA == 1)
/**
 * @brief       启动DMA连续采集
 *
 * @param       无
 *
 * @retval      无
 */
void adc_start_dma(void)
{
    if (HAL_ADC_Start_DMA(&sg_adc_handle, (uint32_t *)sg_adc_values, ADC_CHANNEL_NUM) != HAL_OK)
    {
        log_e("ADC DMA start failed");
    }
    else
    {
        log_d("ADC DMA started");
    }
}

/**
 * @brief       停止DMA采集
 *
 * @param       无
 *
 * @retval      无
 */
void adc_stop_dma(void)
{
    HAL_ADC_Stop_DMA(&sg_adc_handle);
    log_d("ADC DMA stopped");
}

/**
 * @brief       获取DMA缓冲区中ADC值
 *
 * @param[in]   index 通道索引（0~ADC_CHANNEL_NUM-1）
 *
 * @retval      ADC值（0~ADC_MAX_VALUE）
 *
 * @note        如果启用了滤波（ADC_FILTER_ENABLE=1），返回值已经过滤波
 */
uint16_t adc_get_value(uint8_t index)
{
    if (index < ADC_CHANNEL_NUM)
    {
#if (ADC_FILTER_ENABLE == 1)
        return adc_filter(sg_adc_values[index], index);
#else
        return sg_adc_values[index];
#endif
    }

    return 0;
}

/**
 * @brief       获取DMA缓冲区中的电压值
 *
 * @param[in]   index 通道索引（0~ADC_CHANNEL_NUM-1）
 *
 * @retval      电压值（mV）
 *
 * @note        如果启用了滤波，返回值已经过滤波
 */
uint16_t adc_get_voltage(uint8_t index)
{
    uint16_t adc_value = adc_get_value(index);
    uint32_t voltage = (uint32_t)adc_value * ADC_VREF_MV / ADC_MAX_VALUE;
    
    return (uint16_t)voltage;
}

#else
/* DMA未使能时，这些函数为空实现 */
void adc_start_dma(void) { log_w("DMA not enabled"); }
void adc_stop_dma(void) { }
uint16_t adc_get_value(uint8_t index) { (void)index; return 0; }
uint16_t adc_get_voltage(uint8_t index) { (void)index; return 0; }
#endif

/**
 * @brief       读取内部温度传感器
 *
 * @param       无
 *
 * @retval      温度值(℃)
 *
 * @note        使用内部温度传感器测量芯片温度
 */
float adc_read_temperature(void)
{
    uint16_t temp_adc = adc_read_channel(ADC_CHANNEL_TEMPSENSOR);
    float temp_voltage = (float)temp_adc * ADC_VREF_MV / ADC_MAX_VALUE;
    float temperature = (ADC_TEMP_V25_MV - temp_voltage) / ADC_TEMP_AVG_SLOPE + 25.0f;
    
    log_d("Chip temperature: %.2f℃", temperature);
    return temperature;
}

/**
 * @brief       读取内部参考电压
 *
 * @param       无
 *
 * @retval      参考电压值(V)
 *
 * @note        内部参考电压约为1.2V
 */
float adc_read_vrefint(void)
{
    uint16_t vrefint_adc = adc_read_channel(ADC_CHANNEL_VREFINT);
    float vrefint = (float)vrefint_adc * ADC_VREF_MV / ADC_MAX_VALUE / 1000.0f;
    
    log_d("Internal VREF: %.3fV", vrefint);
    return vrefint;
}

/**
 * @brief       获取VDDA电压
 *
 * @param       无
 *
 * @retval      VDDA电压(V)
 *
 * @note        通过内部参考电压反推VDDA
 */
float adc_get_vdda(void)
{
    uint16_t vrefint_adc = adc_read_channel(ADC_CHANNEL_VREFINT);
    float vdda = 1.2f * ADC_MAX_VALUE / vrefint_adc;
    
    log_d("VDDA voltage: %.3fV", vdda);
    return vdda;
}

/**
 * @brief       获取ADC状态
 *
 * @param       无
 *
 * @retval      ADC当前状态
 */
ADC_State_e adc_get_state(void)
{
    return sg_adc_state;
}

/**
 * @brief       打印ADC状态（调试接口）
 *
 * @param       无
 *
 * @retval      无
 */
void adc_print_status(void)
{
    const char *state_str[] = {
        "IDLE",
        "BUSY",
        "CONVERTING",
        "DMA",
        "ERROR"
    };
    
    if (sg_adc_state < 5)
    {
        log_i("ADC State: %s", state_str[sg_adc_state]);
    }
    else
    {
        log_i("ADC State: UNKNOWN");
    }
}

/**
 * @brief       打印所有通道值（调试接口）
 *
 * @param       无
 *
 * @retval      无
 */
void adc_print_all_channels(void)
{
#if (ADC_USE_DMA == 1)
    uint8_t i;
    
    log_i("ADC Channel Values:");
    for (i = 0; i < ADC_CHANNEL_NUM; i++)
    {
        uint16_t value = adc_get_value(i);
        uint16_t voltage = adc_get_voltage(i);
        log_i("  Channel %d: %u (0x%04X), %u mV", i, value, value, voltage);
    }
#else
    log_w("DMA not enabled, cannot print all channels");
#endif
}
